
#include <string.h>

#include "../lib/type.h"
#include <jxos_config.h>
#include "jxos_task.h"
#if (JXOS_MALLOC_ENABLE == 1)
#include "jxos_malloc.h"
#endif
#if (JXOS_REGISTRY_ENABLE == 1)
#include "jxos_registry.h"
#endif

#if (JXOS_TASK_ENABLE == 1)
typedef enum
{
    TASK_STATUS_Running,
    TASK_STATUS_Ready,
    TASK_STATUS_Supspended,
    TASK_STATUS_Block
}TASK_STATUS;

typedef struct
{
	TASK_FUNCTION function;
	const char* name;
	void* parameter;
	uint8_t status;
} TASK_STRUCT;

static uint8_t task_list_pionter;
static TASK_STRUCT task_list[TASK_MAX];
static uint8_t task_count;

#if (JXOS_MALLOC_ENABLE == 1)
JXOS_MALLOC_MEM_POOL_STRUCT tesk_mem_pool;
#endif

void jxos_task_init(void)
{
	uint8_t i;
#if (JXOS_MALLOC_ENABLE == 1)
    tesk_mem_pool.mem_pool = (void*)task_list;
    tesk_mem_pool.len = sizeof(TASK_STRUCT)*TASK_MAX;
    tesk_mem_pool.offset = 0;
#endif
    task_count = 0;
	for(i = 0; i < TASK_MAX; i++){
		task_list[i].function = 0;
		task_list[i].name = 0;
		task_list[i].parameter = 0;
		task_list[i].status = TASK_STATUS_Block;
	}
}

JXOS_TASK_HANDLE jxos_task_create(TASK_FUNCTION function, const char* name, void* parameter)
{
    TASK_STRUCT* h = 0;
#if (JXOS_MALLOC_ENABLE == 1)
    if(jxos_malloc_set_mem_pool(&tesk_mem_pool) == 0){
        while(1);
    }
#endif
    if((function == 0)
        ||(name == 0)){
        return 0;
    }

#if (JXOS_MALLOC_ENABLE == 1)
    h = jxos_malloc(sizeof(TASK_STRUCT));
#else
    if(task_count < TASK_MAX){
        h = &(task_list[task_count]);
    }
#endif
    if(h != 0){
        h->function = function;
        h->name = name;
        h->parameter = parameter;
        h->status = TASK_STATUS_Ready;
#if (JXOS_REGISTRY_ENABLE == 1)
            jxos_registry_register(name, h);
#endif
        task_count++;
        return (JXOS_TASK_HANDLE)h;
    }
    else{
        return 0;
    }
}

uint8_t jxos_task_resume(JXOS_TASK_HANDLE task_h)
{
    TASK_STRUCT* h = task_h;
#if (JXOS_MALLOC_ENABLE == 1)
    if((task_h == 0)
       ||((void*)task_h < (void*)(tesk_mem_pool.mem_pool))
       ||((void*)task_h > (void*)(tesk_mem_pool.mem_pool+tesk_mem_pool.offset))){
        return 0;
    }
#endif
    h->status = TASK_STATUS_Ready;
    return 1;
}

uint8_t jxos_task_suspended(JXOS_TASK_HANDLE task_h)
{
    TASK_STRUCT* h = task_h;
#if (JXOS_MALLOC_ENABLE == 1)
    if((task_h == 0)
       ||((void*)task_h < (void*)(tesk_mem_pool.mem_pool))
       ||((void*)task_h > (void*)(tesk_mem_pool.mem_pool+tesk_mem_pool.offset))){
        return 0;
    }
#endif
    h->status = TASK_STATUS_Supspended;
    return 1;
}

/*
uint8_t* jxos_task_get_name(JXOS_TASK_HANDLE task_h)
{
    TASK_STRUCT* h = task_h;
    return (uint8_t*)(h->name);
}
*/

void jxos_task_schedule(void)
{
    task_list_pionter = 0;
    while(1){
        if(task_list[task_list_pionter].status == TASK_STATUS_Ready){
            task_list[task_list_pionter].status = TASK_STATUS_Running;
#if (JXOS_Compiler_optimization_1 == 1)
            task_list[task_list_pionter].function();
#else
            task_list[task_list_pionter].function(task_list_pionter, task_list[task_list_pionter].parameter);
#endif
            task_list[task_list_pionter].status = TASK_STATUS_Ready;
        }
        task_list_pionter++;
        if(task_list_pionter >= task_count){
            task_list_pionter = 0;
        }
    }
}

#endif

